package com.xiaomazi.security.filter;

import cn.hutool.core.util.StrUtil;
import com.xiaomazi.common.utils.R;
import com.xiaomazi.common.utils.ResponseUtil;
import com.xiaomazi.security.entity.SecurityUser;
import com.xiaomazi.security.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * @program: llxy-parent
 * @description: 访问过滤器
 * @author: 小马子
 * @create: 2023-03-18 15:36
 **/

public class TokenAuthenticationFilter extends OncePerRequestFilter {
    
    private RedisTemplate<String,Object> redisTemplate;

    public TokenAuthenticationFilter(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws ServletException, IOException {
        // token置于header里
        String token = req.getHeader("token");
        if(StrUtil.isBlank(token)) {
            chain.doFilter(req, res);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = null;
        try {
            authentication = getAuthentication(token);
        } catch (Exception e) {
            ResponseUtil.out(res, R.error().message("错误的令牌或令牌过期啦！请重新登陆"));
            return;
        }
        if (null != authentication) {
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } else {
            ResponseUtil.out(res, R.error().message("认证失败啦！请重新登陆"));
            return;
        }

        chain.doFilter(req, res);

    }

    private UsernamePasswordAuthenticationToken getAuthentication(String token) {

        try {
            Claims claims = JwtUtil.parseJWT(token);
            String username = claims.getSubject();
            if (StrUtil.isBlank(username)){
                return null;
            }
//            List<String> permissionValueList  = (List<String>) redisTemplate.opsForValue().get("login:" + username);
            SecurityUser securityUser = (SecurityUser) redisTemplate.opsForValue().get("login:" + username);
            if (null == securityUser){
                return null;
            }
            return new UsernamePasswordAuthenticationToken(securityUser,token,securityUser.getAuthorities());
//            if (null == permissionValueList){
//                return null;
//            }
//            if (!permissionValueList.isEmpty()){
//                List<SimpleGrantedAuthority> authorities = permissionValueList.stream()
//                        .map(SimpleGrantedAuthority::new)
//                        .filter(s -> StrUtil.isNotBlank(s.getAuthority()))
//                        .collect(Collectors.toList());
//                return new UsernamePasswordAuthenticationToken(username, token, authorities);
//            }
//            return new UsernamePasswordAuthenticationToken(username, token, Collections.EMPTY_LIST);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
